package org.example.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SecureDigestAlgorithm;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import javax.crypto.SecretKey;

import java.time.Instant;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

/**
 * @Description: token的制作和管理
 * @Author: 曹震
 * @Date: 2024/11/23 12:25
 */
@Component
@PropertySource("classpath:key.properties")
public class JwtToken {
    @Value("${TOKEN.KEY}")
    private String base64Secret; // 从配置文件中读取 Base64 编码的密钥
    private static final SecureDigestAlgorithm<SecretKey, SecretKey> ALGORITHM = Jwts.SIG.HS256;
    private static SecretKey KEY;

    private static final long ACCESS_EXPIRE = 7 * 24 * 60 * 60 * 1000;  // 7天过期

    @PostConstruct
    public void initKey() {
        // 初始化 KEY，解码 Base64
        KEY = Keys.hmacShaKeyFor(Base64.getDecoder().decode(base64Secret));
    }

    // 生成Token
    public static String createToken(String userId) {
        String uuid = UUID.randomUUID().toString();
        Date expireDate = Date.from(Instant.now().plusMillis(ACCESS_EXPIRE));

        return Jwts.builder()
                .header()
                .add("typ", "JWT")
                .add("alg", "HS256")
                .and()
                .claim("userId", userId)
                .id(uuid)
                .expiration(expireDate)
                .issuedAt(new Date())
                .signWith(KEY, ALGORITHM)
                .compact();
    }

    // 解析 Token
    public static Jws<Claims> parseToken(String token) {
        return Jwts.parser()
                .verifyWith(KEY)
                .build()
                .parseSignedClaims(token);
    }

    // 校验 Token 是否过期
    public static boolean isTokenExpired(String token) {
        try {
            Jws<Claims> jwsClaims = parseToken(token);
            Date expiration = jwsClaims.getPayload().getExpiration();
            return expiration.before(new Date());
        } catch (ExpiredJwtException e) {
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return true;
        }
    }

    // 判断 Token 是否即将过期（30 分钟以内）
    public static boolean isTokenExpiringSoon(Claims claims) {
        Date expirationDate = claims.getExpiration();
        long timeLeft = expirationDate.getTime() - System.currentTimeMillis();
        return timeLeft < 30 * 60 * 1000;
    }

    // 延长 Token 有效期（+3天）
    public static String extendTokenExpiration(Claims claims) {
        String username = claims.getSubject();
        long newExpirationTime = System.currentTimeMillis() + 3 * 24 * 60 * 60 * 1000;

        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(newExpirationTime))
                .signWith(KEY, ALGORITHM)
                .compact();
    }

    // 校验 Token 是否有效
    public static boolean validateToken(String token) {
        try {
            Jws<Claims> claims = parseToken(token);
            return !isTokenExpired(token);
        } catch (Exception e) {
            return false;
        }
    }

    // 从 Token 中提取 userId
    public static String getUserIdFromToken(String token) {
        try {
            Jws<Claims> claims = parseToken(token);
            return claims.getBody().get("userId", String.class);
        } catch (Exception e) {
            return null;
        }
    }
}
